import {create, StateCreator} from "zustand";
import {devtools, persist} from 'zustand/middleware';
import type {CSSProperties} from "react";


export interface Component {
    id: number
    name: string // 组件名
    props: any // 组件属性
    children?: Component[]
    parentId?: number // 父组件id
    desc?: string // 组件描述
    styles?: CSSProperties // 组件样式

}

interface State {
    components: Component[]
    mode: 'edit' | 'preview';
    currentComponentId: number | null
    currentComponent: Component | null
}

interface Action {
    addComponent: (component: Component, parentId?: number) => void
    deleteComponent: (componentId: number) => void
    updateComponentProps: (componentId: number, props: any) => void
    updateComponentStyles: (componentId: number, styles: CSSProperties, replace?: boolean) => void
    setCurrentComponent: (componentId: number) => void
    setMode: (mode: State['mode']) => void;
    replaceComponents: (components: string) => void // 替换components
    moveComponent: (componentId: number, parentId: number, position: string) => void // 移动元素位置
    insertComponentByPosition: (component: Component, dropComponentId: number, parentId: number, position: string) => void  // 根据位置插入组件
}

const creator: StateCreator<State & Action> = (set, get) => ({
    // 组件列表
    components: [
        {
            id: 1,
            name: 'Page',
            props: {},
            desc: '页面',
        }
    ],
    currentComponentId: null, // 当前选中组件id
    currentComponent: null, // 当前选中组件
    mode: 'edit',
    setMode: (mode) => set({mode}),
    addComponent: (component, parentId) =>
        set((state) => {
            // 如果没有父组件，直接添加
            if (!parentId) return {components: [...state.components, component]}
            // 找到父组件
            const parent = getComponentById(parentId, state.components)
            // 如果没有父组件，直接添加
            if (!parent) return {components: [...state.components, component]}
            // 添加子组件的父组件id
            component.parentId = parentId
            // 如果没有子组件，创建子组件
            if (!parent.children) {
                parent.children = [component]
            } else {
                // 有则添加
                parent.children.push(component)
            }
            // 更新组件
            return {components: [...state.components]}
        }),
    deleteComponent: (componentId) => {
        if (!componentId) return;
        const component = getComponentById(componentId, get().components)
        if (!component) return;
        if (component.parentId) {
            const parent = getComponentById(component.parentId, get().components)
            if (!parent) return;
            parent.children = parent.children?.filter((item) => item.id !== componentId)
            set({components: [...get().components]})
        }

    },
    updateComponentProps: (componentId, props) => {
        if (!componentId) return;
        const component = getComponentById(componentId, get().components)
        if (!component) return;
        component.props = {...component.props, ...props}
        set({components: [...get().components]})
    },
    setCurrentComponent: (componentId) => {
        set((state) => ({
            currentComponentId: componentId,
            currentComponent: getComponentById(componentId, state.components)
        }))
    },
    updateComponentStyles: (componentId, styles, replace = false) => {
        const component = getComponentById(componentId, get().components)
        if (!component) return;
        component.styles = replace ? {...styles} : {...component.styles, ...styles}
        set({components: [...get().components]})
    },
    replaceComponents: (string) => {
        set({components: JSON.parse(string)})
    },
    moveComponent: (componentId, parentId, position) => {
        const componentChildren = getComponentById(parentId, get().components)?.children
        if (!componentChildren) return
        const currentIndex = componentChildren.findIndex(item => item.id === componentId)
        if (position === "up" && componentChildren.length > 1) {
            if (currentIndex <= 0) return;
            const temp = componentChildren[currentIndex]
            componentChildren[currentIndex] = componentChildren[currentIndex - 1]
            componentChildren[currentIndex - 1] = temp
        }
        if (position === "down" && currentIndex < componentChildren.length - 1) {
            if (currentIndex >= componentChildren.length - 1) return;
            const temp = componentChildren[currentIndex]
            componentChildren[currentIndex] = componentChildren[currentIndex + 1]
            componentChildren[currentIndex + 1] = temp
        }
        set({components: [...get().components]})
    },
    insertComponentByPosition: (component, dropComponentId, parentId, position) => {
        // 查找拖拽组件的子组件是否包含被放置的组件
        const isDropComponentChildren = getComponentById(dropComponentId, component?.children)
        if(isDropComponentChildren) return;
        // 找到被放置的组件的父组件
        const parent = getComponentById(parentId, get().components)
        // 找到被放置的容器组件位置
        const dropComponentIndex = parent?.children?.findIndex(item => item.id === dropComponentId)
        const newComponent = {...component}
        if (dropComponentIndex === undefined) return
        // 判断是否是父组件的子组件 返回移动前的索引
        const isParentChildrenIndex = parent?.children?.findIndex(item => item.id === component.id)

        // 如果子组件不存在，直接返回
        if (!isParentChildrenIndex) return;
        // 如果是相邻的拖拽 直接返回
        if(dropComponentIndex - isParentChildrenIndex === -1 && position === "after"
            || dropComponentIndex - isParentChildrenIndex === 1 && position === "before") {
            return;
        }
        // 删除原有组件
        get().deleteComponent(component.id)
        if (parentId !== newComponent.parentId) {
            newComponent.parentId = parentId
        }
        // 判断是否是拖拽源的父组件的子组件
        if (isParentChildrenIndex !== -1) {
            // 是拖拽源的父组件的子组件执行以下逻辑
            if (position === 'after') {
                // 判断插入位置
                if (dropComponentIndex < isParentChildrenIndex) {
                    parent?.children?.splice(dropComponentIndex + 1, 0, newComponent)
                } else {
                    parent?.children?.splice(dropComponentIndex, 0, newComponent)
                }
            }
            if (position === 'before') {
                if (dropComponentIndex > isParentChildrenIndex) {
                    parent?.children?.splice(dropComponentIndex - 1, 0, newComponent)
                } else {
                    parent?.children?.splice(dropComponentIndex, 0, newComponent)
                }
            }
        } else {
            // 不是拖拽源的父组件的子组件执行以下逻辑
            if (position === 'after') {
                parent?.children?.splice(dropComponentIndex + 1, 0, newComponent)
            }
            if (position === 'before') {
                parent?.children?.splice(dropComponentIndex, 0, newComponent)
            }
        }
        set({components: [...get().components]})

    }
})

export const useComponentsStore = create<State & Action>()(
    devtools(persist(creator, {name: "components"}), {
        name: 'components', // 浏览器调试时显示的 store 名称
        enabled: true, // 是否开启调试工具(通常根据当前环境开启/关闭)
    }))


/**
 * 获取组件
 * @param id 组件id
 * @param components 组件列表
 * @returns 组件
 * */
export const getComponentById = (id: number, components: Component[] | Component['children']): Component | null => {
    if (!id || !components) return null
    for (const item of components) {
        if (item?.id === id) return item;
        if (item.children && item.children.length > 0) {
            const result = getComponentById(id, item.children)
            if (result !== null) return result
        }
    }
    return null;
}
